package com.antis.olsl.library.utils;

import android.util.Base64;

import com.antis.olsl.library.MyApplication;

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import timber.log.Timber;

public class RSAEncryptUtil {
    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";
    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    /**
     * 获取公钥的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";
    /*** 获取私钥的key*/
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    /*RSA最大加密明文大小*/
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    public static String RSA_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDc+fzDcXcJl6jcIgM78sXcffmlJSLTPMjrq25i9WLDA8JJnrrUw3BEqRXOXV82BqYN3PI3pqZcd8ocmAn+gueuv2PC0J8LVveCU/2AOg5hRwtrFVO44J0m/VP0MWTNt5TUpK4O1RYew+pYTXuE81/W5p30cDkFvzFIpBCYLqdm+wIDAQAB";
    public static String RSA_PRIVATE_KEY = "";

    /*** 生成密钥对(公钥和私钥)*/
    public static Map<String, Object> genKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        System.out.println("公钥" + Base64.encodeToString(publicKey.getEncoded(), Base64.NO_WRAP));
        System.out.println("私钥" + Base64.encodeToString(privateKey.getEncoded(), Base64.NO_WRAP));
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /**
     * @param content 解密
     */
    public static String decryptByPrivateKey(String content) throws Exception {
//        byte[] encryptedData =  Base64.getDecoder().decode(content);
//        byte[] keyBytes = Base64.getDecoder().decode(privateKey);
        byte[] encryptedData = Base64.decode(content, Base64.NO_WRAP);
        byte[] keyBytes = Base64.decode(RSA_PRIVATE_KEY, Base64.NO_WRAP);
//        byte[] keyBytes = Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData);
    }

    public static String generateEncryptStr(Map<String, Object> map) {
        String paramString = MyApplication.getUserInfo() == null ? JsonParser.toJson(map) : dealParams(map);
        Timber.tag("hhh").e("generateEncryptStr paramString= " + paramString);
        String encryptString = "";
        try {
            encryptString = RSAEncryptUtil.encryptByPublicKey(paramString.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return encryptString;
    }

    private static String dealParams(Map<String, Object> map) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("merchantId", MyApplication.getUserInfo() != null ? MyApplication.getUserInfo().getMerchantId() : "");
        result.put("userId", MyApplication.getUserInfo() != null ? MyApplication.getUserInfo().getUserId() : "");
        result.put("param", map);
        return JsonParser.toJson(result);
    }

    /**
     * @param data 加密
     */
    public static String encryptByPublicKey(byte[] data) throws Exception {
        byte[] keyBytes = Base64.decode(RSA_PUBLIC_KEY, Base64.NO_WRAP);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        // 对数据加密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        String result = Base64.encodeToString(encryptedData, Base64.NO_WRAP);
        return result;
    }

}
